/*
 ------------------------------------------------------------------------------
	willy-player - a simple music player based on SDL.

	Copyright (C) 2011 Pierre Veber
	
	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 3 of the License, or
	(at your option) any later version.
	
	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.
	
	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software Foundation,
	Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
------------------------------------------------------------------------------
*/

#include "precomp.h"

#define DECODE_MSG_NONE		0
#define DECODE_MSG_STOP		1
#define DECODE_MSG_SEEK		2
#define DECODE_MSG_PAUSE	3
#define DECODE_MSG_RESUME	4

Player_t* pPlayerSingleInstance = NULL;

struct Player_t {
	HAudioDevice hAudio;
	HThread hThread;
	int status;
	HAudioList	hPlaylist;
	HAudioFile	hCurrent;
	int nCurrentDecoder;
};

static int fDecodeThreadProc(HThread hThread, void* lpParameter)
{
	ThreadMessage_t msg;
	Player_t* pPlayer = (Player_t*)lpParameter;

	while (pPlayer->status != DECODE_STATUS_STOPPED)
	{
		if (GetThreadMessage(hThread, &msg))
		{
			switch (msg.iMsgCode)
			{
				case DECODE_MSG_PAUSE:
					if (pPlayer->status == DECODE_STATUS_DECODING)
					{
						pPlayer->status = DECODE_STATUS_PAUSED;
						wavePause(pPlayer->hAudio);
					}
					else
					{
						waveRestart(pPlayer->hAudio);
						pPlayer->status = DECODE_STATUS_DECODING;
						TRACE1("Resume %s...", pPlayer->hCurrent->pszFullPath); 
					}
					break;

				case DECODE_MSG_RESUME:
					pPlayer->status = DECODE_STATUS_DECODING;
					TRACE1("Resume %s...", pPlayer->hCurrent->pszFullPath);
					pPlayer->nCurrentDecoder = decoderIndex(pPlayer->hCurrent->pszFullPath);
					if (pPlayer->nCurrentDecoder != ENODEC)
					{
						_g_ppDecoders[pPlayer->nCurrentDecoder]->setAudioDevice(pPlayer->hAudio);
						_g_ppDecoders[pPlayer->nCurrentDecoder]->prepare(pPlayer->hCurrent->pszFullPath);
						waveReset(pPlayer->hAudio);
					}
					break;

				case DECODE_MSG_SEEK:
					if ( (pPlayer->nCurrentDecoder != ENODEC) && (pPlayer->status == DECODE_STATUS_DECODING) )
					{
						TRACE1("Seeking %s...", pPlayer->hCurrent->pszFullPath);
						_g_ppDecoders[pPlayer->nCurrentDecoder]->seek((int)msg.ulParam1);
					}
					break;

				case DECODE_MSG_STOP:
					if ( (pPlayer->nCurrentDecoder != ENODEC) && (pPlayer->status == DECODE_STATUS_DECODING) )
					{
						TRACE1("Stopping %s...", pPlayer->hCurrent->pszFullPath);
						_g_ppDecoders[pPlayer->nCurrentDecoder]->stop();
						pPlayer->status = DECODE_STATUS_STOPPED;
					}
					break;

				default:
					break;
			}
		}
		if ( pPlayer->hCurrent != NULL )
		{
			switch (pPlayer->status)
			{
				/* do decoding */
				case DECODE_STATUS_DECODING:
					{
						if (pPlayer->nCurrentDecoder != ENODEC)
						{
							int res = _g_ppDecoders[pPlayer->nCurrentDecoder]->decode();
							if (res == -1)
							{
								TRACE("Decoder ended.");
								pPlayer->status = DECODE_STATUS_FINISHED;
								_g_ppDecoders[pPlayer->nCurrentDecoder]->stop();
							}
						}
					}
					break;
				
				default:
					usleep(100000);
					break;
			}
		}
		else
		{
			/* sleep for 100 ms */
			usleep(100000);
		}
	}
	return 0;
}

HPlayer playerCreate (HAudioDevice hAudio)
{
	if (pPlayerSingleInstance == NULL) 
	{
		pPlayerSingleInstance = (Player_t*)malloc(sizeof(Player_t));

		if (pPlayerSingleInstance != NULL)
		{
			pPlayerSingleInstance->hAudio = hAudio;
			pPlayerSingleInstance->hCurrent = NULL;
			pPlayerSingleInstance->hPlaylist = NULL;
			pPlayerSingleInstance->hThread = NULL;
			pPlayerSingleInstance->status = DECODE_STATUS_NONE;
		}
	}
	return pPlayerSingleInstance;
}

int playerQueue(Player_t* pPlayer, AudioFile_t* pFile)
{
	pPlayer->hCurrent = pFile;
	return 0;
}

int playerResume(Player_t* pPlayer)
{
	if (pPlayer->hThread == NULL)
	{
		pPlayer->hThread = CreateThread(fDecodeThreadProc, pPlayer);
		if (pPlayer->hThread == NULL)
		{
			TRACE("Cannot create player thread!");
			return -1;
		}
	}
	return PostThreadMessage(pPlayer->hThread, DECODE_MSG_RESUME, 0, 0);
}

int playerPause(Player_t* pPlayer)
{
	if (pPlayer->hThread != NULL)
	{
		return PostThreadMessage(pPlayer->hThread, DECODE_MSG_PAUSE, 0, 0);
	}
	return 0;
}

int playerSeek(Player_t* pPlayer, int amt)
{
	if (pPlayer->hThread != NULL)
	{
		return PostThreadMessage(pPlayer->hThread, DECODE_MSG_SEEK, (unsigned long)amt, 0);
	}
	return 0;
}

int playerStop(Player_t* pPlayer)
{
	if (pPlayer->hThread != NULL)
	{
		return PostThreadMessage(pPlayer->hThread, DECODE_MSG_STOP, 0, 0);
	}
	return 0;
}

int playerGetInfo(Player_t* pPlayer)
{
	return 0;
}

void playerDelete(Player_t* pPlayer)
{
	if ( (pPlayerSingleInstance != NULL) && (pPlayer == pPlayerSingleInstance) )
	{
		/* struct cleanup */

		free(pPlayerSingleInstance);
		pPlayerSingleInstance = NULL;
	}
}

